import React from 'react'
import { connect } from 'react-redux'
import menuRoute from "routes/menuRoute";

function getValidChildren(children){
  return React.isValidElement(children) ? children : React.createElement('span', null, children);
}

/**
 * 原理
 * 通过元素 data-control 的值，找到 config 中的 key，把 config 对应 key 的值写到对应元素的属性中
 *
 * 控制组件
 * 目的是让所有组件都有一个受控的中心，初衷是当整个系统的某个组件进行统一更改时可以在这里统一设置
 * 比如组件的 显示隐藏、样式、禁用启用、只读可写 等等
 * 在本系统中主要目的是干掉fp（大量的显示隐藏逻辑）以及功能树权限（大量的只读逻辑）的设置
 * 简单来说就是给系统里所有你需要控制的组件打上标记
 * 然后在这里更改他们的props，进行对应的组件控制
 * 本来更改props使用hoc更好，可以使用 extends WrappedComponent、 super.render().props.children 拿到JSX树
 * 然后 return React.cloneElement(super.render(), props, super.render().props.children)
 * 但是里面有dom检索，所以为了更少的检查，使用组件的方式来控制特定的一段代码
 * 否则使用hoc每次都需要检索整个组件，性能太低
 * 所以放弃了优雅的写法
 * 要不就参照vue和angularJS的指令写法
 * 但是需要重写官方的 instantiateReactComponent
 * 包括下面直接引用的 ReactCompositeComponentWrapper 和 ReactNativeComponent 两个类
 * 工作量太大，放弃，闲暇时间可以搞一搞，工作上就算了
 *
 * 暂定的检查的props： data-control（对应HTML的 data-* ），这个命名放出去当参数没啥意义
 *
 * PS:这玩意写成hoc就是React版的指令啊，能解决效率问题就好了
 *
 * 2019/6/24 added By ZaraNengap
 * 现在为了应付新权限改造，所有页面需要增加只读、可写权限
 * 他们的设计里只针对按钮、表单控件、a标签对应的禁用和所有控件的显隐
 * 而且确实没有注入更多props的需求，后端也不提供支持
 * 所以这里只针对集中特定的action进行操作，不再支持直接注入config以及任何props的支持
 * 现在的config直接从redux中获取，数据从新权限菜单里获取
 * 现在仅仅支持disabled以及显隐的操作，对应的注入方法为为标签增加 data-control 属性
 * 属性值为页面的key和对应的action组成，以'.'隔开，例如 'component-lib.disabled'
 * 详细例子见组件库内例子
 *
 */
class Control extends React.Component {

  constructor(props) {
    super(props);
  }

  scanChildren = children => {
    const { controlConfig, currentPage } = this.props;
    let nowKey = menuRoute.getMenuItemByAttr(currentPage[currentPage.length - 1].key, 'key').key;
    return React.Children.map(children, child => {
      if(typeof child !== 'string') {
        if(child === null){
          return child;
        }
        if(child.props.children && typeof child.props.children === 'object')
        //props是不可扩展的，所以更改props只能复制
          child = React.cloneElement(child, { children: this.scanChildren(child.props.children) });
        let configProps = {};
        if(child.props['data-control']) {
          let dataControl = child.props['data-control'];
          if(dataControl instanceof Array) {
            dataControl = dataControl.find(item => {
              if(typeof item === 'string') {
                return item.split('.')[0] === nowKey
              } else {
                return item.key === nowKey;
              }
            });
          }
          if(dataControl) {
            let sections, key, action;
            if(typeof dataControl === 'string') {
              sections = dataControl.split('.');
              key = sections[0];
              action = sections[1];
            } else {
              key = dataControl.key;
            }
            if(nowKey === key && controlConfig.indexOf(key) > -1) {
              if(action) {
                if(action === 'hidden')
                  return null;
                else {
                  configProps = { [action]: true }
                }
              } else {
                configProps = dataControl.props;
              }
            }
          }
        }
        return React.cloneElement(child, configProps);
      } else {
        return child;
      }
    });
  };

  render(){
    const { children, disabled, user } = this.props;
    return getValidChildren((disabled || !user.enableNewPermission) ? children : this.scanChildren(children));
  }
}

Control.propTypes = {
  disabled: React.PropTypes.bool
};


function mapStateToProps(state) {
  return {
    controlConfig: state.main.controlConfig,
    currentPage: state.main.currentPage,
    user: state.login.user
  }
}

export default connect(mapStateToProps)(Control);
